#include "Object.h"

#include <cstddef>
#include <memory.h>
#include "Containers/String.h"
#include "Containers/SharedObjectPtr.h"
#include "Containers/Any.h"
#include "Reflection/ObjectPtr.h"
#include "Reflection/ClassImplement.h"
#include "Reflection/NativeFieldProperty.h"
#include "Reflection/NativeFunction.h"
#include "Reflection/FunctionList.h"
#include "Reflection/PropertyList.h"
#include "ScriptRuntime/Type/ScriptContent.h"
#include "ScriptRuntime/Type/GSharpClass.h"

#include "ObjectM.h"

//base class of script object 
class RObject_SCRIPT_BASE : public RObject
{
public:    
    static RObject* CreateInstance(void* InMemory)
    {
        return new (InMemory) RObject_SCRIPT_BASE();
    }

    virtual CString ToString() override
    {
        uint64_t VirtuanFunctionIndex=0;
        auto FunctionID=GetScriptContent()->GetClass()->Functions->VirtualFunctionTable[VirtuanFunctionIndex];
        auto Function=SFunctionID::FindFunction(FunctionID);
        RObjectPtr Self= TSharedObjectPtr<RObject>(const_cast<RObject_SCRIPT_BASE*>(this));
        return AnyCast<CString>(Function->Invoke({Self}));
    }
};


CClass* RObject_Reflector::GetStaticClass()
{
    static CClass* Standalone= GenerateClass();
    return Standalone;
}

CClass* RObject_Reflector::GenerateClass()
{
    CNativeClass* Field=new TClass<RObject>( U"RObject" 
        , nullptr, RObject_Reflector::PostConstructField);

    Field->NewScriptNativeInstanceFunc=RObject_SCRIPT_BASE::CreateInstance;

    return Field;

}
void RObject_Reflector::PostConstructField()
{
    CClass*  Field = GetStaticClass();
    Field->SharedPtrType=RObject::StaticSharedPtrType();
    Field->WeakPtrType=RObject::StaticWeakPtrType();

    {
        CNativeFunction* NativeFunction = new CNativeFunction(
            Field->Functions
            ,U"ToString"
            , CGetType<CString>()()
            ,{}
            ,{}
            );
        NativeFunction->MarkAsVirtual();
        
        NativeFunction->SetCppBody([](const TVector<CAny>& InArgs)->CAny
        {
            auto Self= AnyCast<TSharedObjectPtr<RObject>>(InArgs[0]);
            return Self->ToString();
        });
    }

}




CClass* RObject::StaticClass()                      
{                                                   
    return RObject_Reflector::GetStaticClass();    
}                                                    
CClass* RObject::GetClass() const                 
{                
    if(_ScriptContent)
    {
        return _ScriptContent->GetClass();
    }                                    
    return RObject_Reflector::GetStaticClass();                         \
}                                  

static uint8_t Register=(RObject_Reflector::GetStaticClass(),0);

CType* RObject::StaticSharedPtrType()
{
    return WH::TReflectionType<TSharedObjectPtr<RObject>>::FindOrCreateType();
}

CType* RObject::GetSharedPtrType() const
{
    return StaticSharedPtrType();
}


CType* RObject::StaticWeakPtrType()
{
    return WH::TReflectionType<TWeakObjectPtr<RObject>>::FindOrCreateType();  
}

CType* RObject::GetWeakPtrType() const
{
    return StaticWeakPtrType();    
}